#include "stdafx.hpp"
#include "ColligereSearchDiscogs.hpp"
#include "ColligereUtils.hpp"
#include "ColligereXmlUtils.hpp"

col::SearchDiscogs::SearchDiscogs()
{
}

col::SearchDiscogs::SearchDiscogs ( const wxString &rTerm )
{
	SetTerm ( rTerm );
}

void col::SearchDiscogs::SetTerm ( const wxString &rTerm )
{
	mSearchTerm = rTerm;
}

col::SearchDiscogs::SearchResultDeque col::SearchDiscogs::Search()
{
	using namespace boost;

	wxASSERT ( !mSearchTerm.empty() );

	const wxURI uri ( str ( format ( "%1%/search?type=all&q=%2%&f=xml&api_key=1e65230c49" ) % 
		GetServerAddress() % mSearchTerm ) );

	SearchResultDeque results;

	wxString data;
	get_webpage ( uri, data );

	const long ret ( ParseSearchResults ( data, results ) );

	if  ( ret < 0 )
	{
		wxLogError ( "Unable to parse search results from the server." );
	}
	else if ( ret == 0 )
	{
		wxLogMessage ( "No results found." );
	}
	return results;
}

col::Artist col::SearchDiscogs::DownloadResult 
( const SearchDiscogs::SearchResult &rResult )
{
	using namespace boost;

	const wxString id ( rResult.GetUri().AfterLast('/') );
	const wxURI uri ( str ( format ( "%1%/release/%2%?f=xml&api_key=1e65230c49" ) % 
		GetServerAddress() % id ) );

	wxString data;
	get_webpage ( uri, data );
	if ( !data.empty() )
	{
		return ParseDatabaseItem ( data );
	}
	return Artist();
}

col::Artist col::SearchDiscogs::ParseDatabaseItem ( const wxString &rFromData )
{
	typedef XmlUtils xu;

	wxStringInputStream in ( rFromData );
	wxXmlDocument doc ( in );

	if ( !doc.IsOk() || doc.GetRoot()->GetAttribute ( "stat" ) != "ok" )
	{
		return Artist();
	}

	Artist artist ( xu::GetNodeContent 
		( xu::FindNode ( doc.GetRoot(), "name" ) ),
		xu::GetNodeContent 
		( xu::FindNode ( doc.GetRoot(), "country" ) ), empty_string );

	Album album;
	album.SetAlbum ( xu::GetNodeContent ( xu::FindNode ( doc.GetRoot(), "title" ) ) );
	album.SetYear ( xu::GetNodeContent ( xu::FindNode ( doc.GetRoot(), "released" ) ) );

	foreach ( const wxXmlNode *style, xu::FindNodes ( doc.GetRoot(), "style" ) )
	{
		if ( !album.GetGenre().empty() )
		{
			album.SetGenre ( album.GetGenre() + wxString(" / ") + 
				xu::GetNodeContent ( style ) );
		}
		else
		{
			album.SetGenre ( xu::GetNodeContent ( style ) );
		}
	}
	album.SetExtInfo ( xu::GetNodeContent ( xu::FindNode ( doc.GetRoot(), "notes" ) ) );
	album.SetLabel ( xu::GetNodeAttribute ( xu::FindNode ( doc.GetRoot(), "label" ), "name" ) );
	album.SetCatalogNum ( xu::GetNodeAttribute ( xu::FindNode ( doc.GetRoot(), "label" ), "catno" ) );
	album.SetFormat ( xu::GetNodeAttribute ( xu::FindNode 
		( doc.GetRoot(), "format" ), "name" ) );

	foreach ( const wxXmlNode *t, xu::FindNodes ( doc.GetRoot(), "track" ) )
	{
		album.AddChild ( Track 
			( xu::GetNodeContent ( xu::FindNode ( t, "position" ) ),
			xu::GetNodeContent ( xu::FindNode ( t, "title" ) ),
			xu::GetNodeContent ( xu::FindNode ( t, "duration" ) ) ) );
	}

	artist.AddChild ( album );

	return artist;
}

long col::SearchDiscogs::ParseSearchResults ( const wxString &rFromData,
											 SearchResultDeque &rTo )
{
	wxStringInputStream in ( rFromData );
	wxXmlDocument doc ( in );

	if ( !doc.IsOk() || doc.GetRoot()->GetAttribute ( "stat" ) != "ok" )
	{
		return -1;
	}
	foreach  ( const wxXmlNode *n, 
		XmlUtils::FindNodes ( doc.GetRoot(), "result" ) )
	{
		if ( XmlUtils::GetNodeAttribute ( n, "type" ) == "release" )
		{
			const wxString title ( XmlUtils::GetNodeContent 
				( XmlUtils::FindNode ( n, "title") ) );
			const wxString uri ( XmlUtils::GetNodeContent 
				( XmlUtils::FindNode ( n, "uri") ) );
			rTo.push_back ( SearchResult ( title, uri ) );
		}
	}
	return rTo.size();
}

const wxString col::SearchDiscogs::GetServerAddress()
{
	return "http://www.discogs.com";
}

/////////////////////////////////////
// SearchDiscogs::SearchResult
/////////////////////////////////////

col::SearchDiscogs::SearchResult::SearchResult() 
{ 
}

col::SearchDiscogs::SearchResult::SearchResult ( const wxString &rTitle, 
												const wxString &rUri ) 
												: mTitle ( rTitle ), mUri ( rUri ) 
{ 
}

const wxString &col::SearchDiscogs::SearchResult::GetTitle() const 
{ 
	return mTitle; 
}

const wxString &col::SearchDiscogs::SearchResult::GetUri() const 
{ 
	return mUri; 
}